﻿namespace TestTool.Tests.Common.Discovery
{
    using System;
    using System.Runtime.InteropServices;

    public static class OSInfo
    {
        private const int PRODUCT_BUSINESS = 6;
        private const int PRODUCT_BUSINESS_N = 0x10;
        private const int PRODUCT_CLUSTER_SERVER = 0x12;
        private const int PRODUCT_DATACENTER_SERVER = 8;
        private const int PRODUCT_DATACENTER_SERVER_CORE = 12;
        private const int PRODUCT_ENTERPRISE = 4;
        private const int PRODUCT_ENTERPRISE_N = 0x1b;
        private const int PRODUCT_ENTERPRISE_SERVER = 10;
        private const int PRODUCT_ENTERPRISE_SERVER_CORE = 14;
        private const int PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x29;
        private const int PRODUCT_ENTERPRISE_SERVER_IA64 = 15;
        private const int PRODUCT_ENTERPRISE_SERVER_V = 0x26;
        private const int PRODUCT_HOME_BASIC = 2;
        private const int PRODUCT_HOME_BASIC_N = 5;
        private const int PRODUCT_HOME_PREMIUM = 3;
        private const int PRODUCT_HOME_PREMIUM_N = 0x1a;
        private const int PRODUCT_HOME_SERVER = 0x13;
        private const int PRODUCT_HYPERV = 0x2a;
        private const int PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 30;
        private const int PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x20;
        private const int PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x1f;
        private const int PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x18;
        private const int PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x23;
        private const int PRODUCT_SMALLBUSINESS_SERVER = 9;
        private const int PRODUCT_SMALLBUSINESS_SERVER_PREMIUM = 0x19;
        private const int PRODUCT_STANDARD_SERVER = 7;
        private const int PRODUCT_STANDARD_SERVER_CORE = 13;
        private const int PRODUCT_STANDARD_SERVER_CORE_V = 40;
        private const int PRODUCT_STANDARD_SERVER_V = 0x24;
        private const int PRODUCT_STARTER = 11;
        private const int PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x17;
        private const int PRODUCT_STORAGE_EXPRESS_SERVER = 20;
        private const int PRODUCT_STORAGE_STANDARD_SERVER = 0x15;
        private const int PRODUCT_STORAGE_WORKGROUP_SERVER = 0x16;
        private const int PRODUCT_ULTIMATE = 1;
        private const int PRODUCT_ULTIMATE_N = 0x1c;
        private const int PRODUCT_UNDEFINED = 0;
        private const int PRODUCT_WEB_SERVER = 0x11;
        private const int PRODUCT_WEB_SERVER_CORE = 0x1d;
        private static string s_Edition;
        private static string s_Name;
        private const int VER_NT_DOMAIN_CONTROLLER = 2;
        private const int VER_NT_SERVER = 3;
        private const int VER_NT_WORKSTATION = 1;
        private const int VER_SUITE_BLADE = 0x400;
        private const int VER_SUITE_DATACENTER = 0x80;
        private const int VER_SUITE_ENTERPRISE = 2;
        private const int VER_SUITE_PERSONAL = 0x200;
        private const int VER_SUITE_SINGLEUSERTS = 0x100;
        private const int VER_SUITE_SMALLBUSINESS = 1;
        private const int VER_SUITE_TERMINAL = 0x10;

        [DllImport("Kernel32.dll")]
        internal static extern bool GetProductInfo(int osMajorVersion, int osMinorVersion, int spMajorVersion, int spMinorVersion, out int edition);
        [DllImport("kernel32.dll")]
        private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo);

        public static int Bits
        {
            get
            {
                return (IntPtr.Size * 8);
            }
        }

        public static int BuildVersion
        {
            get
            {
                return Environment.OSVersion.Version.Build;
            }
        }

        public static string Edition
        {
            get
            {
                if (s_Edition != null)
                {
                    return s_Edition;
                }
                string str = string.Empty;
                OperatingSystem oSVersion = Environment.OSVersion;
                OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX {
                    dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX))
                };
                if (GetVersionEx(ref osVersionInfo))
                {
                    int num5;
                    int major = oSVersion.Version.Major;
                    int minor = oSVersion.Version.Minor;
                    byte wProductType = osVersionInfo.wProductType;
                    short wSuiteMask = osVersionInfo.wSuiteMask;
                    switch (major)
                    {
                        case 4:
                            switch (wProductType)
                            {
                                case 1:
                                    str = "Workstation";
                                    break;

                                case 3:
                                    if ((wSuiteMask & 2) != 0)
                                    {
                                        str = "Enterprise Server";
                                    }
                                    else
                                    {
                                        str = "Standard Server";
                                    }
                                    break;
                            }
                            goto Label_0397;

                        case 5:
                            switch (wProductType)
                            {
                                case 1:
                                    if ((wSuiteMask & 0x200) != 0)
                                    {
                                        str = "Home";
                                    }
                                    else
                                    {
                                        str = "Professional";
                                    }
                                    break;

                                case 3:
                                    if (minor == 0)
                                    {
                                        if ((wSuiteMask & 0x80) != 0)
                                        {
                                            str = "Datacenter Server";
                                        }
                                        else if ((wSuiteMask & 2) != 0)
                                        {
                                            str = "Advanced Server";
                                        }
                                        else
                                        {
                                            str = "Server";
                                        }
                                    }
                                    else if ((wSuiteMask & 0x80) != 0)
                                    {
                                        str = "Datacenter";
                                    }
                                    else if ((wSuiteMask & 2) != 0)
                                    {
                                        str = "Enterprise";
                                    }
                                    else if ((wSuiteMask & 0x400) != 0)
                                    {
                                        str = "Web Edition";
                                    }
                                    else
                                    {
                                        str = "Standard";
                                    }
                                    break;
                            }
                            goto Label_0397;
                    }
                    if ((major == 6) && GetProductInfo(major, minor, osVersionInfo.wServicePackMajor, osVersionInfo.wServicePackMinor, out num5))
                    {
                        switch (num5)
                        {
                            case 0:
                                str = "Unknown product";
                                break;

                            case 1:
                                str = "Ultimate";
                                break;

                            case 2:
                                str = "Home Basic";
                                break;

                            case 3:
                                str = "Home Premium";
                                break;

                            case 4:
                                str = "Enterprise";
                                break;

                            case 5:
                                str = "Home Basic N";
                                break;

                            case 6:
                                str = "Business";
                                break;

                            case 7:
                                str = "Standard Server";
                                break;

                            case 8:
                                str = "Datacenter Server";
                                break;

                            case 9:
                                str = "Windows Small Business Server";
                                break;

                            case 10:
                                str = "Enterprise Server";
                                break;

                            case 11:
                                str = "Starter";
                                break;

                            case 12:
                                str = "Datacenter Server (core installation)";
                                break;

                            case 13:
                                str = "Standard Server (core installation)";
                                break;

                            case 14:
                                str = "Enterprise Server (core installation)";
                                break;

                            case 15:
                                str = "Enterprise Server for Itanium-based Systems";
                                break;

                            case 0x10:
                                str = "Business N";
                                break;

                            case 0x11:
                                str = "Web Server";
                                break;

                            case 0x12:
                                str = "HPC Edition";
                                break;

                            case 20:
                                str = "Express Storage Server";
                                break;

                            case 0x15:
                                str = "Standard Storage Server";
                                break;

                            case 0x16:
                                str = "Workgroup Storage Server";
                                break;

                            case 0x17:
                                str = "Enterprise Storage Server";
                                break;

                            case 0x18:
                                str = "Windows Essential Server Solutions";
                                break;

                            case 0x1a:
                                str = "Home Premium N";
                                break;

                            case 0x1b:
                                str = "Enterprise N";
                                break;

                            case 0x1c:
                                str = "Ultimate N";
                                break;

                            case 0x1d:
                                str = "Web Server (core installation)";
                                break;

                            case 30:
                                str = "Windows Essential Business Management Server";
                                break;

                            case 0x1f:
                                str = "Windows Essential Business Security Server";
                                break;

                            case 0x20:
                                str = "Windows Essential Business Messaging Server";
                                break;

                            case 0x23:
                                str = "Windows Essential Server Solutions without Hyper-V";
                                break;

                            case 0x24:
                                str = "Standard Server without Hyper-V";
                                break;

                            case 0x26:
                                str = "Enterprise Server without Hyper-V";
                                break;

                            case 40:
                                str = "Standard Server without Hyper-V (core installation)";
                                break;

                            case 0x29:
                                str = "Enterprise Server without Hyper-V (core installation)";
                                break;

                            case 0x2a:
                                str = "Microsoft Hyper-V Server";
                                break;
                        }
                    }
                }
            Label_0397:
                s_Edition = str;
                return str;
            }
        }

        public static int MajorVersion
        {
            get
            {
                return Environment.OSVersion.Version.Major;
            }
        }

        public static int MinorVersion
        {
            get
            {
                return Environment.OSVersion.Version.Minor;
            }
        }

        public static string Name
        {
            get
            {
                if (s_Name != null)
                {
                    return s_Name;
                }
                string str = "unknown";
                OperatingSystem oSVersion = Environment.OSVersion;
                OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX {
                    dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX))
                };
                if (GetVersionEx(ref osVersionInfo))
                {
                    int major = oSVersion.Version.Major;
                    int minor = oSVersion.Version.Minor;
                    switch (oSVersion.Platform)
                    {
                        case PlatformID.Win32Windows:
                            if (major == 4)
                            {
                                string szCSDVersion = osVersionInfo.szCSDVersion;
                                switch (minor)
                                {
                                    case 0:
                                        switch (szCSDVersion)
                                        {
                                            case "B":
                                            case "C":
                                                str = "Windows 95 OSR2";
                                                goto Label_01DF;
                                        }
                                        str = "Windows 95";
                                        goto Label_01DF;

                                    case 10:
                                        if (szCSDVersion == "A")
                                        {
                                            str = "Windows 98 Second Edition";
                                        }
                                        else
                                        {
                                            str = "Windows 98";
                                        }
                                        goto Label_01DF;

                                    case 90:
                                        str = "Windows Me";
                                        goto Label_01DF;
                                }
                            }
                            break;

                        case PlatformID.Win32NT:
                        {
                            byte wProductType = osVersionInfo.wProductType;
                            switch (major)
                            {
                                case 3:
                                    str = "Windows NT 3.51";
                                    goto Label_01DF;

                                case 4:
                                    switch (wProductType)
                                    {
                                        case 1:
                                            str = "Windows NT 4.0";
                                            break;

                                        case 3:
                                            str = "Windows NT 4.0 Server";
                                            break;
                                    }
                                    goto Label_01DF;

                                case 5:
                                    switch (minor)
                                    {
                                        case 0:
                                            str = "Windows 2000";
                                            break;

                                        case 1:
                                            str = "Windows XP";
                                            break;

                                        case 2:
                                            str = "Windows Server 2003";
                                            break;
                                    }
                                    goto Label_01DF;

                                case 6:
                                    switch (wProductType)
                                    {
                                        case 1:
                                            switch (minor)
                                            {
                                                case 0:
                                                    str = "Windows Vista";
                                                    break;

                                                case 1:
                                                    str = "Windows 7";
                                                    break;
                                            }
                                            break;

                                        case 3:
                                            str = "Windows Server 2008";
                                            break;
                                    }
                                    goto Label_01DF;
                            }
                            break;
                        }
                    }
                }
            Label_01DF:
                s_Name = str;
                return str;
            }
        }

        public static int RevisionVersion
        {
            get
            {
                return Environment.OSVersion.Version.Revision;
            }
        }

        public static string ServicePack
        {
            get
            {
                string szCSDVersion = string.Empty;
                OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX {
                    dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX))
                };
                if (GetVersionEx(ref osVersionInfo))
                {
                    szCSDVersion = osVersionInfo.szCSDVersion;
                }
                return szCSDVersion;
            }
        }

        public static System.Version Version
        {
            get
            {
                return Environment.OSVersion.Version;
            }
        }

        public static string VersionString
        {
            get
            {
                return Environment.OSVersion.Version.ToString();
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct OSVERSIONINFOEX
        {
            public int dwOSVersionInfoSize;
            public int dwMajorVersion;
            public int dwMinorVersion;
            public int dwBuildNumber;
            public int dwPlatformId;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst=0x80)]
            public string szCSDVersion;
            public short wServicePackMajor;
            public short wServicePackMinor;
            public short wSuiteMask;
            public byte wProductType;
            public byte wReserved;
        }
    }
}

